const express = require('express');
const router = express.Router();
const debug = require('debug')('a-sokio-yun:server');
const axios = require('axios');
const mongoose = require('../../db/db.js');
const deviceShe = require('../../db/cloudControl/deviceSchema');
const userMod = require('../../db/cloudControl/userMod');

const clients = new Map();
let awaitKaiBoClients = [];
let taskData2 = '';

// 服务器启动时更新所有设备状态为掉线
userMod
	.find({})
	.then((docs) => {
		if (docs?.length > 0) {
			docs.forEach((doc) => {
				const deviceMod = mongoose.model('device_' + doc.userName, deviceShe);
				deviceMod.updateMany({}, { taskStatus: '掉线' }, { upsert: false }).then();
			});
		}
	})
	.catch((err) => console.error('更新设备状态失败:', err));

// WebSocket 连接处理
router.ws('/:userName/:deviceName/:device_UUID/:device_height/:device_width/:taskStatus', async (ws, req) => {
	console.log(req.params)
	const { userName, deviceName, device_UUID, device_height, device_width, taskStatus } = req.params;
	console.log( userName, deviceName, device_UUID, device_height, device_width, taskStatus )
	const wsid = deviceName === 'liuLanQi' ? `liuLanQi_${userName}` : `${userName}_${deviceName}`;

	try {
		// 设备连接处理
		if (deviceName !== 'liuLanQi') {
			const now = new Date();
			const dataStr = `${now.getMonth() + 1}月${now.getDate()}日${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;

			const upData = {
				taskStatus,
				socketId: wsid,
				updateTime: dataStr,
				device_width,
				device_height,
				device_UUID,
			};
			console.log(upData)
			const deviceMod = mongoose.model(`device_${userName}`, deviceShe);
			await deviceMod.updateOne({ deviceName }, upData, { upsert: true });
			console.log(`设备链接: ${wsid}`);
		} else {
			debug(`浏览器上线: ${wsid}`);
		}

		// 存储 WebSocket 实例
		clients.set(wsid, ws);
		setupWebSocketHandlers(ws, wsid, userName);
	} catch (error) {
		console.error(`WebSocket 连接错误: ${error.message}`);
		ws.terminate();
	}
});

// WebSocket 处理器设置
function setupWebSocketHandlers(ws, wsid, userName) {
	ws.isAlive = true;

	ws.on('pong', () => {
		debug(`收到 ${wsid} 的 Pong 消息`);
		ws.isAlive = true;
	});

	const heartbeatTimer = setInterval(() => {
		if (!ws.isAlive) {
			console.log(`服务器, ${wsid} 的心跳异常`);
			clearInterval(heartbeatTimer);
			return ws.terminate();
		}

		ws.isAlive = false;
		debug(`服务器,给 ${wsid} 发送心跳包`);
		ws.ping('');
	}, 30000);

	ws.on('message', (msg) => onMessage(userName, wsid, ws, msg));
	ws.on('close', (code, reason) => handleClose(ws, wsid, userName, code, reason, heartbeatTimer));
}

// 消息处理函数
async function onMessage(userName, wsid, ws, msg) {
	if (Buffer.isBuffer(msg)) {
		const wsidarr = ['liuLanQi_' + userName];
		sendToClients(wsidarr, JSON.stringify({ type: 'image/jpeg', wsid: wsid, binaryArr: msg }));
		return;
	}

	const dic = isJSON(msg);
	if (!dic) {
		debug(wsid, '的消息无须解析', msg);
		return;
	}

	switch (dic.type) {
		case 'touPing_start':
			sendToClients(dic.socketIds, JSON.stringify({ type: 'touPing_start', touPingDic: dic.touPingDic }));
			break;
		case 'touPing_stop':
			sendToClients(dic.socketIds, JSON.stringify({ type: 'touPing_stop' }));
			break;
		case 'startAction':
			sendToClients(dic.wsid, JSON.stringify(dic));
			break;
		case '状态':
			await handleStatusUpdate(dic.data, userName);
			break;
		case '信息':
			await handleInfoUpdate(wsid, dic.data, userName);
			break;
		case 'ping':
			ws.isAlive = true;
			ws.send(JSON.stringify({ type: 'pong' }));
			break;
		default:
			console.log('无效数据:', dic);
	}
}

// 状态更新处理
async function handleStatusUpdate(data, userName) {
	const now = new Date();
	const updateTime = `${now.getMonth() + 1}月${now.getDate()}日${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
	const upData = {
		taskStatus: data.taskStatus,
		updateTime,
		taskName: data.taskName,
	};

	debug(`用户:${data.userName}的设备:${data.deviceName}更新状态了`);
	const deviceMod = mongoose.model(`device_${data.userName}`, deviceShe);
	await deviceMod.updateOne({ deviceName: data.deviceName }, upData, { upsert: true });
}

// 信息更新处理
async function handleInfoUpdate(wsid, data, userName) {
	debug(`用户:${wsid}更新信息`);
	const deviceMod = mongoose.model(`device_${userName}`, deviceShe);
	await deviceMod.updateOne({ socketId: wsid }, { deviceMsg: data }, { upsert: true });
}

// 关闭连接处理
async function handleClose(ws, wsid, userName, code, reason, heartbeatTimer) {
	clearInterval(heartbeatTimer);

	if (clients.get(wsid) !== ws) {
		console.log(`旧ws掉线: ${wsid}, code:${code}, reason:${reason}, 已重连`);
		return;
	}

	clients.delete(wsid);
	console.log(`ws断开: ${wsid}, code:${code}, reason:${reason}, 踢下线`);

	try {
		if (wsid === 'liuLanQi_root' || wsid.includes('liuLanQi_')) {
			const message = JSON.stringify({ type: 'touPing_stop' });
			const targetClients =
				wsid === 'liuLanQi_root'
					? Array.from(clients.values())
					: Array.from(clients.entries())
							.filter(([id]) => id.startsWith(userName + '_'))
							.map(([, client]) => client);

			targetClients.forEach((client) => client.send(message));
		} else {
			const deviceMod = mongoose.model(`device_${userName}`, deviceShe);
			await deviceMod.updateOne({ socketId: wsid }, { taskStatus: '掉线' }, { upsert: false });
		}
	} catch (error) {
		console.error(`处理连接关闭时出错: ${error.message}`);
	}
}

// 消息发送函数
async function sendToClients(clientIds, data) {
	try {
		const obj = JSON.parse(data);

		if (obj?.serverData?.taskName === '开始任务') {
			for (const clientId of clientIds) {
				const ws = clients.get(clientId);
				if (ws) {
					ws.send(data);
					const delay = getRandomInt(obj.serverData.taskData.startIntervalMin * 1000, obj.serverData.taskData.startIntervalMax * 1000);
					await sleep(delay);
				}
			}
		} else if (obj?.serverData?.taskName === '定时直播') {
			const ws = clients.get(clientIds[0]);
			awaitKaiBoClients = [...clientIds];
			taskData2 = data;

			if (ws) {
				const modifiedObj = {
					...obj,
					serverData: {
						...obj.serverData,
						taskData: {
							...obj.serverData.taskData,
							jance: 1,
						},
					},
				};
				ws.send(JSON.stringify(modifiedObj));
			}
		} else {
			clientIds.forEach((clientId) => {
				const ws = clients.get(clientId);
				ws?.send(data);
			});
		}
	} catch (error) {
		console.error(`发送消息错误: ${error.message}`, { clientIds });
	}
}

// 工具函数
async function sleep(ms) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}

function getRandomInt(min, max) {
	min = Math.ceil(min);
	max = Math.floor(max);
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

function isJSON(str) {
	if (typeof str === 'string') {
		try {
			const obj = JSON.parse(str);
			return typeof obj === 'object' && obj ? obj : false;
		} catch (e) {
			debug(e);
			return false;
		}
	}
	console.log(`非预期的数据类型: ${typeof str}`);
	return false;
}

router.post('/faTast', (req, res) => {
	const { data } = req.body;
	if (data.userName) {
		faTask(res, data, data.userName);
	} else {
		res.json({
			code: -1,
			msg: '失败:用户登录失效',
		});
	}
});

async function faTask(res, data, userName) {
	try {
		debug('服务器收到任务,开始分发');
		const taskTask = JSON.stringify({
			type: 'deviceTask',
			serverData: {
				taskName: data.taskName,
				taskData: data.taskData?.taskID || data.taskData,
				timeStamp: data.timeStamp,
			},
		});

		const wsIds = [...(data.socketIdArr || [])];

		if (data.groupDocArr?.length > 0) {
			const deviceMod = mongoose.model(`device_${userName}`, deviceShe);
			for (const groupDoc of data.groupDocArr) {
				const devices = await deviceMod.find({ groupId: groupDoc.groupId });
				wsIds.push(...devices.map((device) => device.socketId).filter((id) => !wsIds.includes(id)));
			}
		}

		debug('下发任务给wsIds', wsIds);
		await sendToClients(wsIds, taskTask);
		res.json({ code: 1, msg: '成功' });
	} catch (error) {
		res.json({ code: -1, msg: `下发任务出错:${error.message}` });
	}
}

// 状态查询路由
router.get('/wss', (req, res) => {
	const zhangHao = req.query.z;
	if (zhangHao) {
		const deviceNum = Array.from(clients.keys()).filter((id) => id.startsWith(`${zhangHao}_`)).length;
		res.send(`ws(${zhangHao}):${deviceNum}个`);
	} else {
		res.send(`ws(总):${clients.size}个`);
	}
});

router.get('/wsid', async (req, res) => {
	const { id: deviceName, userName } = req.query;
	const wsid = `${userName}_${deviceName}`;

	try {
		const deviceMod = mongoose.model(`device_${userName}`, deviceShe);
		const docs = await userMod.find({});

		let isDeviceNumber = 0
		let user = {}
		for (const doc of docs) {
			if(doc.userName == userName){
				// console.log(doc)
				user = doc
				break
			}
		}
		if (!user) {
			return res.json({ code: -1, msg: '用户不存在' });
		}
		const count = await deviceMod.countDocuments({});
		// console.log('userName',userName)
		// console.log('count:',count)
		isDeviceNumber += count ? count : 0
		for (const u of docs) {
			if(u.parent == user._id.toString()) {
				isDeviceNumber += u.maxDeviceNum
				// console.log('u.maxDeviceNum:',u.maxDeviceNum)
			}
		}

		const deviceNum = Array.from(clients.keys()).filter((id) => id.startsWith(`${userName}_`)).length;
		console.log('deviceNum:',deviceNum)
		debug(`本次上线id(${wsid}),用户(${userName})的最大占控数量${user.maxDeviceNum}个`);

		const existingWs = clients.get(wsid);
		if (existingWs) {
			console.log(`连接ID${wsid}已存在的连接对象,关闭先前的连接`);
			existingWs.terminate();
			return res.json({ code: -1, msg: '疑似重复,已剔除老设备' });
		}
		// console.log('test:',deviceNum,isDeviceNumber,user.maxDeviceNum)
		if (isDeviceNumber >= user.maxDeviceNum) {
			return res.json({ code: -1, msg: `设备超过设定数量:${user.maxDeviceNum}` });
		}

		res.json({ code: 1, msg: '可以上线' });
	} catch (error) {
		res.json({ code: -1, msg: `服务器:${error.message}` });
	}
});

// 企业微信消息发送
async function qywxsend(str) {
	try {
		const response = await axios.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=d817ae9d-ed16-46d4-bf2a-cdcfc8ff50d0', {
			msgtype: 'text',
			text: { content: str },
		});
		return response.data.errmsg === 'ok';
	} catch (error) {
		console.error('企业微信发送失败:', error);
		return false;
	}
}

module.exports = router;
